import datetime
from collections import Counter, defaultdict

from django.db.models import F, Max, Value
from django.shortcuts import render

from monitor.tasks import TASKS
from monitor.utils import filter_queryset
from processor.constants import OS
from processor.exporter import EXPORT_TYPES, EXPORTERS
from processor.utils import date_format, get_quarter_periods
from processor.models import (
    Logger, StockBasic, RSIStructure, RSIExtremum, RSITrend, MACPool, 
    Shareholding, ConceptQuarter, ConceptDaily, ConceptStockDaily,
    StockConceptHistory
)


def login(request):
    return render(request, 'login.html')


def index(request):
    resp_data = {
        'os': OS,
        'tasks': {
            name: {
                k: v
                for k, v in task.items()
                if k != 'func'
            }
            for name, task in TASKS.items()
        },
        'periods': get_quarter_periods()
    }
    return render(request, 'index.html', resp_data)


def ma(request):
    selected_source = request.GET.get('source', 'Tushare')
    source_list = ("Tushare", "Wind")
    source = 1 if selected_source == 'Tushare' else 2
    date_list = MACPool.objects.values_list('fdate', flat=True).distinct()
    date_list = list(map(lambda x: str(x), date_list))
    
    selected_date = request.GET.get('date', max(date_list + ['']))

    queryset = MACPool.objects.filter(fdate = selected_date).filter(source = source)

    resp_data = {
        'selected_date': selected_date,
        'selected_source': selected_source,
        'source_list': source_list,
        'date_list': date_list,
        'pool_data': {
            "观察池%d"%pool: queryset.filter(pid = pool).values_list('field', flat = True)
            for pool, _ in MACPool.POOLS
        }
    }
    return render(request, 'ma.html', resp_data)


def rsi_analysis(request):
    resp_data = {
        'rsi_extre_indexes': RSIExtremum.INDEX_FIELDS,
    }
    return render(request, 'rsi_analysis.html', resp_data)


def rsi_extremum(request):
    '''
        历史/范围 最大最小值
    '''
    rsi_extre = {}

    for field in RSIExtremum.INDEX_FIELDS:
        rsi_extre[field] = {}
        date_field = f'{field}_date'
        for period, period_symbol in  [(1, 'd'), (2, 'w')]:
            extremum_queryset = RSIExtremum.objects.filter(period=period)

            date_list = extremum_queryset.values_list(
                date_field, flat=True
            ).order_by(
                f'-{date_field}'
            ).distinct()
            
            selected_date = request.GET.get(
                f'{date_field}_{period_symbol}', 
                date_list.first()
            )
            selected_date = date_format(selected_date, datetime.date)

            rsi_extre[field][period_symbol] = {
                'field': field,
                'period': period,
                'period_symbol': period_symbol,
                'selected_date': selected_date,
                'date_list': date_list,
                'data': extremum_queryset.filter(
                    **{date_field: selected_date},
                ).values(
                    'scode', 'sname', 'industry', 'lastest_rsi', 
                    value=F(field), 
                ).order_by('value')
            }
    '''
        构造返回数据
    '''
    resp_data = {'rsi_extre': rsi_extre}
    return render(request, 'rsi_extremum.html', resp_data)


def rsi_filter(request):
    daily_date_list = list(map(str, RSITrend.objects.filter(
        period = RSITrend.DAILY
    ).order_by('-fdate').values_list('fdate', flat=True)))
    weekly_date_list = list(map(str, RSITrend.objects.filter(
        period = RSITrend.WEEKLY
    ).order_by('-fdate').values_list('fdate', flat=True)))
    industry_list = list(StockBasic.objects.exclude(
        industry=''
    ).values_list(
        'industry', flat=True
    ).distinct())

    selected_period = RSITrend.DAILY
    period_symbol = 'D'
    selected_date = max(daily_date_list)

    if request.GET.get('period', '') == 'weekly':
        selected_period = RSITrend.WEEKLY
        period_symbol = 'W'
        selected_date = max(weekly_date_list)
        
    selected_date = request.GET.get('date', selected_date)
    selected_trend = request.GET.get('trend', '')
    selected_industry = request.GET.get('industry', '')
    
    try:
        rsi_trend_record = RSITrend.objects.get(
            fdate = selected_date,
            period = selected_period,
        )

        rsi_trend = [
            {   
                'key': k,
                'trend': f'{period_symbol}bg-{k[-1].upper()}',
                'scode': row['scode'],
                'sname': row['sname'],
                'industry': row['industry'],
                'check_point': row['check_point'].upper(),
                'check_point_date': row['point_' + row['check_point']]['date'],
                'check_point_rsi': row['point_' + row['check_point']]['rsi'],
                'check_point_close': row['point_' + row['check_point']]['close'],
                'n_rsi': row['point_n']['rsi'],
                'n_close': row['point_n']['close'],
            }
            for k in ('bg_a', 'bg_b', 'bg_c', 'bg_d', 'bg_e', 'bg_f')
            for row in getattr(rsi_trend_record, k)
            if selected_trend == '' or selected_trend == k
            if selected_industry == '' or row['industry'] == selected_industry
        ]
    except RSITrend.DoesNotExist:
        rsi_trend = []

    resp_data = {
        'selected_period': selected_period,
        'selected_date': selected_date,
        'selected_trend': selected_trend,
        'selected_industry': selected_industry,
        'daily_date_list': daily_date_list,
        'weekly_date_list': weekly_date_list,
        'industry_list': industry_list,
        'rsi_trend': rsi_trend,
    }

    return render(request, 'rsi_filter.html', resp_data)


def log(request):
    selected_date = request.GET.get(
        'timestamp__date',
        Logger.objects.latest('timestamp').timestamp
    )

    date_list = Logger.objects.values_list(
        'timestamp__date', flat=True
    ).distinct().order_by('-timestamp__date')

    queryset = filter_queryset(
        Logger.objects.all(), 
        request, 
        ['level'],
        defaults={
            'timestamp__date': selected_date
        }
    ).order_by('-timestamp')

    resp_data = {
        'selected_date': selected_date,
        'selected_level': request.GET.get('level'),
        'dates': date_list,
        'logs': queryset,
    }
    return render(request, 'log.html', resp_data)


def top10_holder(request):
    resp_data = {
        'holding_periods': Shareholding.objects.values_list(
            'quarter', flat=True
        ).order_by('-quarter').distinct(),
    }
    return render(request, 'top10_holder.html', resp_data)


def holder_number(request):
    return render(request, 'holder_number.html', {})


def achievement(request):
    resp_data = {
        'periods': get_quarter_periods()
    }
    return render(request, 'achievement.html', resp_data)


def export(request):
    resp_data = {
        'sources': EXPORTERS,
        'types': EXPORT_TYPES,
    }
    return render(request, 'export.html', resp_data)


def forecast(request):
    resp_data = {
        'periods': get_quarter_periods()
    }
    return render(request, 'forecast.html', resp_data)


def fund(request):
    resp_data = {
        'periods': get_quarter_periods()
    }
    return render(request, 'fundportfolio.html', resp_data)


def consensus(request):
    resp_data = {
    }
    return render(request, 'consensus.html', resp_data)


def quarter_concept(request):
    resp_data = {
        'periods': list(ConceptQuarter.objects.values_list(
            'quarter', flat=True
        ).distinct().order_by('-quarter')),
        'wind_update_date_list': list(StockConceptHistory.objects.filter(
            source=2
        ).values_list(
            'update_date', flat=True
        ).distinct().order_by('-update_date')),
        'tushare_update_date_list': list(StockConceptHistory.objects.filter(
            source=1
        ).values_list(
            'update_date', flat=True
        ).distinct().order_by('-update_date')),
    }
    return render(request, 'quarter_concept.html', resp_data)


def fresh_price(request):
    resp_data = {
    }
    return render(request, 'freshprice.html', resp_data)


def daily_concept(request):
    resp_data = {
        'trade_dates': ConceptDaily.objects.values_list(
            'trade_date', flat=True
        ).distinct().order_by(
            '-trade_date'
        )
    }
    return render(request, 'daily_concept.html', resp_data)


def daily_concept_stock(request):
    resp_data = {
        'trade_dates': ConceptStockDaily.objects.values_list(
            'trade_date', flat=True
        ).distinct().order_by(
            '-trade_date'
        )
    }
    return render(request, 'daily_concept_stock.html', resp_data)
